package com.canaan.business.service.basic.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.canaan.business.common.enums.inOutStock.StockOccupyStatusEnum;
import com.canaan.business.common.enums.storehouse.StoreHouseLocationTypeEnum;
import com.canaan.business.common.enums.storehouse.StorehouseStockStatusEnum;
import com.canaan.business.domain.basic.WmsStorehouse;
import com.canaan.business.domain.basic.WmsStorehouseArea;
import com.canaan.business.domain.basic.WmsStorehouseLocation;
import com.canaan.business.domain.inOutStock.StorehouseStockCheck;
import com.canaan.business.domain.storehouse.StorehouseStockScrap;
import com.canaan.business.domain.storehouse.WmsStorehouseStock;
import com.canaan.business.mapper.basic.WmsStorehouseLocationMapper;
import com.canaan.business.service.basic.IWmsStorehouseAreaService;
import com.canaan.business.service.basic.IWmsStorehouseLocationService;
import com.canaan.business.service.basic.IWmsStorehouseService;
import com.canaan.business.service.inOutStock.IStorehouseStockCheckService;
import com.canaan.business.service.storehouse.IStorehouseStockScrapService;
import com.canaan.business.service.storehouse.IWmsStorehouseStockService;
import com.canaan.common.exception.ServiceException;
import com.canaan.common.utils.DateUtils;
import com.canaan.common.utils.SecurityUtils;
import com.canaan.common.utils.StringUtils;
import com.canaan.system.service.ISysConfigService;
import org.apache.commons.compress.utils.Lists;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 库位Service业务层处理
 *
 * @author ruoyi
 * @date 2022-11-29
 */
@Service
public class WmsStorehouseLocationServiceImpl implements IWmsStorehouseLocationService
{
    @Resource
    private WmsStorehouseLocationMapper wmsStorehouseLocationMapper;

    @Resource
    private IWmsStorehouseService wmsStorehouseService;

    @Resource
    private IWmsStorehouseAreaService wmsStorehouseAreaService;

    @Resource
    private ISysConfigService sysConfigService;

    @Resource
    private IStorehouseStockCheckService storehouseStockCheckService;

    @Resource
    private IStorehouseStockScrapService storehouseStockScrapService;

    @Resource
    private IWmsStorehouseStockService storehouseStockService;

    /**
     * 查询库位
     *
     * @param id 库位主键
     * @return 库位
     */
    @Override
    public WmsStorehouseLocation selectWmsStorehouseLocationById(Long id)
    {
        return wmsStorehouseLocationMapper.selectWmsStorehouseLocationById(id);
    }

    @Override
    public WmsStorehouseLocation selectWmsStorehouseLocationByNo(String no) {
        return wmsStorehouseLocationMapper.selectWmsStorehouseLocationByNo(no);
    }

    @Override
    public List<WmsStorehouseLocation> selectWmsStorehouseLocationList(String storehouseAreaNo, String productNo) {

        List<WmsStorehouseLocation> locationList = Lists.newArrayList();
        String inStorehouseType = sysConfigService.selectConfigByKey("tactic.instorage");
        WmsStorehouseArea storehouseArea = this.wmsStorehouseAreaService.selectWmsStorehouseAreaByNo(storehouseAreaNo);
        WmsStorehouse storehouse = new WmsStorehouse();
        String storehouseNo = "";
        if (storehouseArea!=null){
            storehouse = wmsStorehouseService.selectWmsStorehouseByNo(storehouseArea.getStorehouseNo());
            storehouseNo = storehouseArea.getStorehouseNo();
       }
        if ("1".equals(inStorehouseType)) {
            // 按库存物料所在库位
            List<String> locationNos = Lists.newArrayList();
            if ("DJC".equals(storehouse.getTypeNo())) {
                // 待检仓
                StorehouseStockCheck check = new StorehouseStockCheck();
                check.setProductNo(productNo);
                check.setStorehouseNo(storehouseNo);
                check.setStorehouseAreaNo(storehouseAreaNo);
                List<StorehouseStockCheck> stockCheckList = storehouseStockCheckService.selectStorehouseStockCheckList2(check);
                locationNos = stockCheckList.stream().map(StorehouseStockCheck::getStorehouseLocationNo).collect(Collectors.toList());
            } else if ("NC".equals(storehouse.getTypeNo())) {
                // 报废仓
                StorehouseStockScrap scrap = new StorehouseStockScrap();
                scrap.setProductNo(productNo);
                scrap.setStorehouseNo(storehouseNo);
                scrap.setStorehouseAreaNo(storehouseAreaNo);
                List<StorehouseStockScrap> stockScrapList = storehouseStockScrapService.selectStorehouseStockScrapList2(scrap);
                locationNos = stockScrapList.stream().map(StorehouseStockScrap::getStorehouseLocationNo).collect(Collectors.toList());
            } else {
                WmsStorehouseStock stock = new WmsStorehouseStock();
                stock.setProductNo(productNo);
                stock.setStorehouseNo(storehouseNo);
                stock.setStorehouseAreaNo(storehouseAreaNo);
                List<WmsStorehouseStock> stockList = storehouseStockService.selectWmsStorehouseStockList2(stock);
                locationNos = stockList.stream().map(WmsStorehouseStock::getStorehouseLocationNo).collect(Collectors.toList());
            }

            if (!locationNos.isEmpty()) {
                WmsStorehouseLocation location = new WmsStorehouseLocation();
                location.setNos(locationNos);
                locationList = wmsStorehouseLocationMapper.selectWmsStorehouseLocationList2(location);
            }

        } else if ("2".equals(inStorehouseType)) {
            // 就近库位推荐（库位编号排序）
            WmsStorehouseLocation location = new WmsStorehouseLocation();
            location.setStorehouseNo(storehouseNo);
            location.setStorehouseAreaNo(storehouseAreaNo);
            locationList = wmsStorehouseLocationMapper.selectWmsStorehouseLocationList2(location);
        } else {
            // 按指定库位
            WmsStorehouseLocation location = new WmsStorehouseLocation();
            location.setStorehouseNo(storehouseNo);
            location.setStorehouseAreaNo(storehouseAreaNo);
            locationList = wmsStorehouseLocationMapper.selectWmsStorehouseLocationList2(location);
        }
        // 排序
        locationList.sort(Comparator.comparing(WmsStorehouseLocation::getNo));
        return locationList;
    }

    /**
     * 查询库位列表
     *
     * @param wmsStorehouseLocation 库位
     * @return 库位
     */
    @Override
    public List<WmsStorehouseLocation> selectWmsStorehouseLocationList(WmsStorehouseLocation wmsStorehouseLocation)
    {
        return wmsStorehouseLocationMapper.selectWmsStorehouseLocationList(wmsStorehouseLocation);
    }

    /**
     * 新增库位
     *
     * @param entity 库位
     * @return 结果
     */
    @Override
    @Transactional
    public WmsStorehouseLocation insertWmsStorehouseLocation(WmsStorehouseLocation entity)
    {
        if(entity == null || entity.getNo() == null){
            throw new ServiceException("缺少库位编号");
        }else if(entity.getName() == null){
            throw new ServiceException("缺少库位名称");
        }
        List<String> nos = new ArrayList<>();
        nos.add(entity.getNo());
        List<String> names = new ArrayList<>();
        names.add(entity.getName());
        List<WmsStorehouseLocation> repeatList = wmsStorehouseLocationMapper.listByNoOrName(nos, names);
        if(!repeatList.isEmpty()){
            //有重复的数据
            WmsStorehouseLocation old = repeatList.stream()
                    .filter(e -> e.getNo().equals(entity.getNo())).findFirst().orElse(null);
            throw new ServiceException(old != null ? "库位编号已存在" : "库位名称已存在");
        }
        entity.setCreateBy(SecurityUtils.getUsername());
        entity.setCreateTime(DateUtils.getNowDate());
        entity.setLocationType(StoreHouseLocationTypeEnum.STORAGE.getCode());
        wmsStorehouseLocationMapper.insertWmsStorehouseLocation(entity);

        WmsStorehouseStock wmsStorehouseStock=new WmsStorehouseStock();
        wmsStorehouseStock.setStorehouseLocationNo(entity.getNo());
        wmsStorehouseStock.setContainerNo("");
        wmsStorehouseStock.setStorehouseAreaNo(entity.getStorehouseAreaNo());
        wmsStorehouseStock.setStorehouseNo(entity.getStorehouseNo());
        wmsStorehouseStock.setStatus(StorehouseStockStatusEnum.NORMAL.getCode());
        wmsStorehouseStock.setTrayNo("");
        wmsStorehouseStock.setCreateBy(SecurityUtils.getUsername());
        wmsStorehouseStock.setCreateTime(DateUtils.getNowDate());
        storehouseStockService.insertWmsStorehouseStock(wmsStorehouseStock);
        return entity;
    }

    /**
     * 修改库位
     *
     * @param entity 库位
     * @return 结果
     */
    @Override
    public int updateWmsStorehouseLocation(WmsStorehouseLocation entity)
    {
        //库位名称校验
        List<String> names = Collections.singletonList(entity.getName());
        List<WmsStorehouseLocation> repeatList = wmsStorehouseLocationMapper.listByNoOrName(null, names);
        repeatList = repeatList.stream().filter(e -> !e.getId().equals(entity.getId())).collect(Collectors.toList());
        if(!repeatList.isEmpty()){
            //有重复的数据
            throw new ServiceException("库位名称已存在");
        }

        entity.setUpdateBy(SecurityUtils.getUsername());
        entity.setUpdateTime(DateUtils.getNowDate());
        return wmsStorehouseLocationMapper.updateWmsStorehouseLocation(entity);
    }

    /**
     * 批量删除库位
     *
     * @param ids 需要删除的库位主键
     * @return 结果
     */
    @Override
    public int deleteWmsStorehouseLocationByIds(Long[] ids)
    {

        return wmsStorehouseLocationMapper.deleteWmsStorehouseLocationByIds(ids);
    }

    /**
     * 删除库位信息
     *
     * @param id 库位主键
     * @return 结果
     */
    @Override
    public int deleteWmsStorehouseLocationById(Long id)
    {
        return wmsStorehouseLocationMapper.deleteWmsStorehouseLocationById(id);
    }

    /**
     * 根据编号或名称查询出列表
     * @param nos 编号列表
     * @param names 名称列表
     * @return 数据列表
     */
    @Override
    public List<WmsStorehouseLocation> listByNoOrName(List<String> nos, List<String> names){
        return wmsStorehouseLocationMapper.listByNoOrName(nos,names);
    }

    /**
     * 导入数据
     * @param list 导入数据列表
     * @return 错误列表
     */
    @Override
    public List<String> importExcel(List<WmsStorehouseLocation> list) {
        List<String> errorList = new ArrayList<>();
        if(StringUtils.isEmpty(list)){
            return errorList;
        }

        List<String> nos = list.stream().filter(e -> e.getNo() != null).map(WmsStorehouseLocation::getNo).collect(Collectors.toList());
        List<String> names = list.stream().filter(e -> e.getName() != null).map(WmsStorehouseLocation::getName).collect(Collectors.toList());
        List<String> storehouseNos = list.stream()
                .filter(e -> e.getStorehouseNo() != null).map(WmsStorehouseLocation::getStorehouseNo).collect(Collectors.toList());
        List<String> areaNos = list.stream()
                .filter(e -> e.getStorehouseAreaNo() != null).map(WmsStorehouseLocation::getStorehouseAreaNo).collect(Collectors.toList());

        //获取重复的数据
        List<WmsStorehouseLocation> oldList = listByNoOrName(nos, names);
        nos = oldList.stream().map(WmsStorehouseLocation::getNo).collect(Collectors.toList());
        names = oldList.stream().map(WmsStorehouseLocation::getName).collect(Collectors.toList());

        //获取仓库列表
        Map<String, WmsStorehouse> storehouseMap = wmsStorehouseService.listByNoOrName(storehouseNos, null).stream()
                .collect(Collectors.toMap(WmsStorehouse::getNo, e -> e));
        //获取库区列表
        Map<String, WmsStorehouseArea> areaMap = wmsStorehouseAreaService.listByNoOrName(areaNos, null).stream()
                .collect(Collectors.toMap(WmsStorehouseArea::getNo, e -> e));
        //行数据校验
        for (int i = 0; i < list.size(); i++) {
            WmsStorehouseLocation entity = list.get(i);

            if(StringUtils.isEmpty(entity.getNo())){
                errorList.add("第" + ( i + 1 ) + "行缺少库位编号");
            }else if(nos.contains(entity.getNo())){
                errorList.add("第" + ( i + 1 ) + "行库位编号已存在");
            }

            if(StringUtils.isEmpty(entity.getName())){
                errorList.add("第" + ( i + 1 ) + "行缺少库位名称");
            }else if(names.contains(entity.getName())){
                errorList.add("第" + ( i + 1 ) + "行库位名称已存在");
            }

            if(!storehouseMap.containsKey(entity.getStorehouseNo())){
                errorList.add("第" + ( i + 1 ) + "行仓库编号不存在");
            }else{
                entity.setStorehouseName(storehouseMap.get(entity.getStorehouseNo()).getName());
            }

            if(!areaMap.containsKey(entity.getStorehouseAreaNo())){
                errorList.add("第" + ( i + 1 ) + "行库区编号不存在");
            }else{
                entity.setStorehouseAreaName(areaMap.get(entity.getStorehouseAreaNo()).getName());
            }

            if(StringUtils.isEmpty(entity.getStatus())){
                entity.setStatus("0");
            }
        }

        if(errorList.size() > 0){
            return errorList;
        }
        //没有什么问题就保存数据
        String username = SecurityUtils.getUsername();
        Date createTime = new Date();
        for (WmsStorehouseLocation location : list) {
            location.setCreateBy(username);
            location.setCreateTime(createTime);
            location.setUpdateBy(null);
            location.setUpdateTime(null);
            wmsStorehouseLocationMapper.insertWmsStorehouseLocation(location);
        }

        return errorList;
    }

    /**
     * 根据库区编号查询仓库列表
     *
     * @param areaNos 库区编号列表
     * @return 仓库集合
     */
    @Override
    public List<WmsStorehouseLocation> listByAreaNos(List<String> areaNos){
        return wmsStorehouseLocationMapper.listByAreaNos(areaNos);
    }

    @Override
    public List<String> listAreaByNos(String nos) {
        List<String> areaList = Lists.newArrayList();
        if (StringUtils.isNotEmpty(nos)){
            String [] str = nos.split(",");
            List<String > list = new ArrayList<>(str.length);
            for (String item : str){
                list.add(item);
            }
            List<WmsStorehouseLocation> locationList = wmsStorehouseLocationMapper.listAreaByNos(list);
            if (CollectionUtil.isNotEmpty(locationList)){
               areaList = locationList.stream().map(WmsStorehouseLocation::getStorehouseAreaNo).distinct().collect(Collectors.toList());
            }
        }
        return areaList;
    }

    @Override
    public WmsStorehouseLocation selectWmsStorehouseLocationByAgvPoint(String agvPositionCode) {
        return wmsStorehouseLocationMapper.selectWmsStorehouseLocationByAgvPoint(agvPositionCode);
    }
}
